# -*- coding: utf-8 -*-
# @Time    : 2019/10/24 14:12
# @Author  : LiHaowen
# @Email   : lihaowen2017@163.com
# @File    : thread_sync.py

import threading
from threading import Lock, RLock
# RLock 可重入的锁
# 在同一个线程中，可以连续调用多次acquire，一定要acquire的次数和release相等
# 线程间还是竞争的，rlock可以在线程内部嵌套函数使用
total = 0
lock = threading.Lock()
rlock = threading.RLock()

def add():
    # dosomething1
    # io操作
    # dosomething2
    global total
    global lock
    global rlock
    for i in range(1000000):
        # lock.acquire()  # 添加锁
        # lock.acquire()  # 死锁原因之一
        # total += 1
        # lock.release()  # 释放锁
        rlock.acquire()  # 添加锁
        rlock.acquire()
        total += 1
        rlock.release()  # 释放锁
        rlock.release()  # 释放锁


def desc():
    global total
    global lock
    global rlock
    for i in range(1000000):
        # lock.acquire()  # 添加锁
        # total -= 1
        # lock.release()  # 释放锁
        rlock.acquire()  # 添加锁
        total -= 1
        rlock.release()  # 释放锁


thread1 = threading.Thread(target=add)
thread2 = threading.Thread(target=desc)

thread1.start()
thread2.start()

# 线程同步机制

def add1(a):
    a += 1


def desc(a):
    a -= 1

"""字节码解析
0 LOAD_FAST                0 (a)
2 LOAD_CONST               1 (1)
4 INPLACE_ADD
6 STORE_FAST               0 (a)

1. load a
2. load 1
3. +
4. 赋值给a
"""
# 一行字节码执行后GIL释放切换到另一线程， 赋值语句时出错a= 1/-1 而不为0
# web，电商网站中库存问题即为该类型问题
import dis

# print(dis.dis(add1))
# print("=========")
# print(dis.dis(desc))

thread1.join()
thread2.join()
# 数值不稳定
print(total)

# 1. 用锁会影响性能
# 2. 锁会引起死锁
# 死锁：1) 未release就继续acquire,函数及子函数连续调用acquire
# 死锁：2) 互相等待 A(a,b)
"""
A (a, b)
acquire(a)
acquire(b)
B(b, a)
acquire(b)
acquire(a)
假定B, A 线程请求资源a，b A先请求a， B先请求b，则后续会导致循环等待
资源竞争的死锁
"""